chore: version packages#1549
Merged
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
6452eef to
8a14479
Compare
8a14479 to
b3d3ef3
Compare
b3d3ef3 to
771775d
Compare
771775d to
785b89a
Compare
785b89a to
9196786
Compare
9196786 to
d93a87d
Compare
d93a87d to
e9d8331
Compare
e9d8331 to
515ced6
Compare
515ced6 to
e775210
Compare
e775210 to
0119ac3
Compare
0119ac3 to
b88f899
Compare
b88f899 to
ff2d2fe
Compare
ff2d2fe to
cbab8e6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@objectstack/cli@7.8.0
Minor Changes
6b60068: fix(cli):
objectstack devpersists data by default (no more:memory:wipe on restart)objectstack devhistorically fell back to a:memory:SQLite database when no--database/OS_DATABASE_URLwas given, so every restart silently wiped all data and AI-authored metadata — you'd build an app, restart, and it would be gone, which makes local app-building unusable.devnow defaults to a persistent, project-anchored SQLite file at<cwd>/.objectstack/data/dev.db(gitignored, per-project). Existing opt-outs are unchanged and take precedence:--fresh(ephemeral temp DB),--database <url>,OS_DATABASE_URL/DATABASE_URL, or an explicit in-memory driver (--database-driver memory/OS_DATABASE_DRIVER=memory). Resolution is extracted into the testableresolveDefaultDevDbUrl()helper.The app-showcase example drops its explicit
:memory:datasource override (which would otherwise route data back to memory and defeat the new default), so it persists across restarts out of the box.Patch Changes
@objectstack/objectql@7.8.0
Minor Changes
a75823a: feat(metadata): expose pending DRAFT metadata (ADR-0033 draft discoverability)
AI-authored metadata lands as drafts (
sys_metadatarows withstate='draft', bound to an app package), but the only list path —getMetaItems— reads the active registry, so drafts were invisible: a just-built app package looked empty and there was no "pending changes" surface.SysMetadataRepository.listDrafts({type?, packageId?})lists draft rows (mirrorslist()but scoped tostate='draft', optionally narrowed by package), returning a light header projection (no body) withpackageId.protocol.listDrafts({packageId?, type?, organizationId?})exposes it over the overlay repo.GET /api/v1/meta/_drafts?packageId=&type=surfaces it to the console. Registered in the REST server before the greedy/meta/:typeroute (and mirrored in the dispatcher) so_draftsis never captured as a metadata type name.Read-only; no behavior change to existing list/publish paths. Powers the upcoming Studio "drafts/pending changes" view and draft-aware package contents.
4fbb86a: feat(packages): consolidate the package subsystem so AI-built app packages surface in Studio
The package subsystem was split across two stores that never met: the in-memory
SchemaRegistry(what the dispatcher's/api/v1/packageslist/detail andgetMetaItems({type:'package'})read — i.e. Studio's package selector) and the durablesys_packagestable (where the AI's auto app package, and anypackage-service publish,were written). Nothing reconciled the two, so an AI-created
app.<name>package neverappeared in Studio.
This unifies them around one write primitive and one read source:
protocol.installPackageis now implemented (it was declared-but-missing). It is thesingle canonical write path: it registers the package in the in-memory registry and
best-effort persists it to
sys_packagesvia thepackageservice. Non-fatal when nopackageservice is wired (registry write still succeeds).POST /api/v1/packagesroutes throughprotocol.installPackage(fallingback to the bare registry write when the protocol is unavailable), so HTTP installs are
durable too.
@objectstack/service-packagereconcilessys_packagesback into the registry onboot, without clobbering filesystem-registered packages — so persisted packages survive a
restart and stay visible in the registry-backed read paths.
@objectstack/service-aiapply_blueprintnow homes an app viaprotocol.installPackage(falling back to the legacypackage-service publish), so theapp package lands where Studio reads it.
Still the legacy
package_idplane — sealedsys_package_versionversioning andcross-environment promotion remain ADR-0027 follow-ups.
e631f1e: feat(metadata): publish a whole app's drafts in one shot (ADR-0033)
After an AI builds an app, its metadata is drafted (bound to an app package) and
had to be published one item at a time. The package-level
POST /packages/:id/publishneeds the
metadataservice (503 when absent, e.g. the showcase) and reads thein-memory registry, not the drafts.
protocol.publishPackageDrafts({ packageId })promotes everysys_metadatadraft row bound to the package to active by reusing the per-item
publishMetaItemprimitive (overridable/lock guards + runtime registryrefresh). Per-item failures are collected, not fatal. No
metadata-servicedependency.
POST /api/v1/packages/:id/publish-draftsexposes it (distinct from theregistry-based
/publish), returning{ success, publishedCount, failedCount, published, failed }.Verified live: an AI-built
app.asset_management(4 drafts) published in one call —all 4 promoted to active, drafts cleared, draft objects became queryable.
36719db: fix: AI-built apps are usable immediately — sync new object tables on publish + emit valid kanban config
Two gaps found by end-to-end testing of an AI-built app:
A freshly-published object couldn't accept records until a server restart. Publishing a drafted object registered it in the in-memory registry but never created its physical table (table sync only ran at boot), so inserts failed with
object_not_found("no such table"). AddedObjectQL.syncObjectSchema(name)(a targeted, idempotent single-object schema sync) and call it from the publish paths (protocol.publishMetaItemandsaveMetaItemmode:'publish', viaensureObjectStorage). Best-effort + non-fatal. New objects are now CRUD-able the moment they're published.AI-generated kanban views rendered as plain lists (and sometimes failed validation). The blueprint
viewBodyemittedlist.type:'kanban'with nokanbanconfig;KanbanConfigSchemarequiresgroupByFieldandcolumns. Added an optionalgroupByto the blueprint view schema (lenient + strict) and haveapply_blueprintsetlist.kanban = { groupByField, columns }— using the view's explicitgroupBywhen given, else inferring the object's firstselectfield. AI-built kanban views now validate, publish, and carry a real group-by field.Patch Changes
6fc2678: fix(metadata): stamp a top-level
nameonviewbodies at the write path so AI/hand-authored views surfacegetMetaItemsonly overlays asys_metadatarow when its parsed body has a top-levelname. Some view producers — notably loose{ list: <ListView> }/{ form: … }fragments that AI tools and hand-authoring emit — pass schema validation but carry no top-levelname, so the view was silently dropped from the object's view list and never appeared as a tab ("validates ≠ surfaces").saveMetaItemnow guarantees a top-levelnameon every view body at the single write chokepoint, BEFORE validation + persistence, so a nameless view is auto-corrected regardless of which authoring path produced it. It deliberately does NOT reshape the document: both thedefineViewcontainer form ({ list, listViews, … }, expanded by the loader) and the{ name, object, viewKind, config }record form are valid and the console consumes both — reshaping a container into a record risks producing an invalid record (e.g. a non-<object>.<key>name) and drops Studio-only fields (isPinned,sortOrder, …). Exported asnormalizeViewMetadataand unit-tested.(Note for follow-up: the
viewmetadata schema is itself a permissive union — it accepts an unknownviewKind, a kanban config missinggroupByField, even{}. Tightening it correctly requires first consolidating the four legitimate view shapes — record / container / flat list / flat form — and is a separate spec change.)Updated dependencies [06f2bbb]
Updated dependencies [f01f9fa]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/service-ai@7.8.0
Minor Changes
6b82e68: feat(ai): zero-package app building — auto-home a blueprint's app in a writable package
When the AI blueprint flow builds an app, it now silently gives that app a writable "home" package (one app ⇒ one
app.<name>package) and binds every drafted artifact (objects, views, dashboards, the app) to it — so a business user never has to create a "package" to start building (the mainstream AI-builder UX: Power Apps' default solution, Salesforce orgs). Packaging/versioning stays an opt-in, later concern.apply_blueprintensures the app package up front (idempotent: reuse if it exists, else create via the runtimepackageservice) and threads itspackageIdthrough everystageDraft→sys_metadata.package_id. The result envelope gainspackage: { id, name, created }.packageservice is resolved lazily (per call, not at plugin-init time) so it works regardless of service-init order and picks up the opt-inmarketplacecapability when present.packageservice is wired, drafting proceeds package-less exactly as before — the build never fails on packaging.Scope/caveats: this stamps the legacy
sys_metadata.package_id(a real grouping + the foundation for later version/export/promote), not the sealedsys_package_versionmodel — full cross-environment promotion and Studio package-selector visibility depend on finishing the runtime package subsystem (ADR-0027), tracked separately. (The showcase example enables themarketplacecapability to exercise this.)4888ea2: feat(ai): add
get_metadata_schematool so the agent can read a type's contract before authoringThe metadata-authoring agent never sees the real spec Zod schemas — it works against a simplified blueprint or sends a free-form
definitionand only learns the true shape from post-hoc validation errors. For complex types (view, dashboard, flow, …) that means guessing, e.g. a kanban view's requiredkanban: { groupByField, columns }block.New
get_metadata_schematool returns the JSON Schema (via Zod v4'stoJSONSchema) derived from the SAME live schemasaveMetaItemvalidates against (getMetadataTypeSchema). Themetadata_authoringskill now instructs the agent to call it before authoring a non-trivial type, so it conforms first time instead of trial-and-error. Read-only; resolves plural type names; returns a graceful error for types that can't be serialized (e.g.object, which the dedicatedcreate_objecttools cover anyway).36719db: fix: AI-built apps are usable immediately — sync new object tables on publish + emit valid kanban config
Two gaps found by end-to-end testing of an AI-built app:
A freshly-published object couldn't accept records until a server restart. Publishing a drafted object registered it in the in-memory registry but never created its physical table (table sync only ran at boot), so inserts failed with
object_not_found("no such table"). AddedObjectQL.syncObjectSchema(name)(a targeted, idempotent single-object schema sync) and call it from the publish paths (protocol.publishMetaItemandsaveMetaItemmode:'publish', viaensureObjectStorage). Best-effort + non-fatal. New objects are now CRUD-able the moment they're published.AI-generated kanban views rendered as plain lists (and sometimes failed validation). The blueprint
viewBodyemittedlist.type:'kanban'with nokanbanconfig;KanbanConfigSchemarequiresgroupByFieldandcolumns. Added an optionalgroupByto the blueprint view schema (lenient + strict) and haveapply_blueprintsetlist.kanban = { groupByField, columns }— using the view's explicitgroupBywhen given, else inferring the object's firstselectfield. AI-built kanban views now validate, publish, and carry a real group-by field.Patch Changes
06f2bbb: fix(ai): make ADR-0033 blueprint authoring work with OpenAI structured outputs
Two bugs surfaced by a live end-to-end run (Studio chat → blueprint → draft → review → publish) against a real model (OpenAI via the Vercel AI Gateway) — both invisible to the existing unit tests:
propose_blueprintfailed against OpenAI strict structured outputs.SolutionBlueprintSchemauses optional fields and a free-formseedDatarecord; OpenAI's strict mode requires every property listed inrequiredand rejects openadditionalProperties, sogenerateObjecterrored ('required' … must include every key in properties) and the agent silently fell back to free-text. AddsSolutionBlueprintStrictSchema— a strict-compatible mirror (optional → nullable, noz.record) used only as thegenerateObjectoutput contract. The lenientSolutionBlueprintSchema(and every existing consumer/test) is unchanged; the blueprint tools strip thenulls the strict contract emits so downstream stays clean.Tool-only assistant turns failed to persist.
ai_messages.contentis required, but an assistant turn that only calls a tool has no text, so the insert failed, the turn was dropped, and the next turn lost context (the agent re-proposed instead of applying the confirmed blueprint).ObjectQLConversationService.addMessagenow synthesizes a readable placeholder from the tool names ((called propose_blueprint)) plus a defensive non-empty fallback.With both fixes the full plan-first loop runs end-to-end on OpenAI models: propose → confirm → batch-draft objects/views/dashboards/app → review/diff → publish.
4fbb86a: feat(packages): consolidate the package subsystem so AI-built app packages surface in Studio
The package subsystem was split across two stores that never met: the in-memory
SchemaRegistry(what the dispatcher's/api/v1/packageslist/detail andgetMetaItems({type:'package'})read — i.e. Studio's package selector) and the durablesys_packagestable (where the AI's auto app package, and anypackage-service publish,were written). Nothing reconciled the two, so an AI-created
app.<name>package neverappeared in Studio.
This unifies them around one write primitive and one read source:
protocol.installPackageis now implemented (it was declared-but-missing). It is thesingle canonical write path: it registers the package in the in-memory registry and
best-effort persists it to
sys_packagesvia thepackageservice. Non-fatal when nopackageservice is wired (registry write still succeeds).POST /api/v1/packagesroutes throughprotocol.installPackage(fallingback to the bare registry write when the protocol is unavailable), so HTTP installs are
durable too.
@objectstack/service-packagereconcilessys_packagesback into the registry onboot, without clobbering filesystem-registered packages — so persisted packages survive a
restart and stay visible in the registry-backed read paths.
@objectstack/service-aiapply_blueprintnow homes an app viaprotocol.installPackage(falling back to the legacypackage-service publish), so theapp package lands where Studio reads it.
Still the legacy
package_idplane — sealedsys_package_versionversioning andcross-environment promotion remain ADR-0027 follow-ups.
328a7c4: fix(ai): AI-authored views now bind to their object and render (kanban as a board, not a list)
An AI-built app's views (including kanban) appeared only as the default list and never as selectable tabs. Diagnosis (vs the working showcase kanban) showed it was a metadata-shape bug in the blueprint's
viewBody, not the renderer or skill: it emitted a bare{ list: {…} }fragment instead of the canonical view record. Three things were missing/wrong:name→getMetaItemsonly surfaces overlay rows whose body hasname, so every AI view was silently dropped from the object's view list;object/viewKind→ the console couldn't bind the view to its object;<object>.<key>-prefixed (the convention the console keys view tabs off).viewBodynow emits{ name: '<object>.<key>', object, viewKind: 'list'|'form', config: <ListView|FormView> }, matching the shape the showcase's own views use (verified against the realViewSchema). End-to-end verified: an AI-built kanban app surfaces 看板 + 列表 as tabs and renders the kanban as a board grouped by status.Updated dependencies [06f2bbb]
Updated dependencies [f01f9fa]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/spec@7.8.0
Minor Changes
36719db: fix: AI-built apps are usable immediately — sync new object tables on publish + emit valid kanban config
Two gaps found by end-to-end testing of an AI-built app:
A freshly-published object couldn't accept records until a server restart. Publishing a drafted object registered it in the in-memory registry but never created its physical table (table sync only ran at boot), so inserts failed with
object_not_found("no such table"). AddedObjectQL.syncObjectSchema(name)(a targeted, idempotent single-object schema sync) and call it from the publish paths (protocol.publishMetaItemandsaveMetaItemmode:'publish', viaensureObjectStorage). Best-effort + non-fatal. New objects are now CRUD-able the moment they're published.AI-generated kanban views rendered as plain lists (and sometimes failed validation). The blueprint
viewBodyemittedlist.type:'kanban'with nokanbanconfig;KanbanConfigSchemarequiresgroupByFieldandcolumns. Added an optionalgroupByto the blueprint view schema (lenient + strict) and haveapply_blueprintsetlist.kanban = { groupByField, columns }— using the view's explicitgroupBywhen given, else inferring the object's firstselectfield. AI-built kanban views now validate, publish, and carry a real group-by field.Patch Changes
06f2bbb: fix(ai): make ADR-0033 blueprint authoring work with OpenAI structured outputs
Two bugs surfaced by a live end-to-end run (Studio chat → blueprint → draft → review → publish) against a real model (OpenAI via the Vercel AI Gateway) — both invisible to the existing unit tests:
propose_blueprintfailed against OpenAI strict structured outputs.SolutionBlueprintSchemauses optional fields and a free-formseedDatarecord; OpenAI's strict mode requires every property listed inrequiredand rejects openadditionalProperties, sogenerateObjecterrored ('required' … must include every key in properties) and the agent silently fell back to free-text. AddsSolutionBlueprintStrictSchema— a strict-compatible mirror (optional → nullable, noz.record) used only as thegenerateObjectoutput contract. The lenientSolutionBlueprintSchema(and every existing consumer/test) is unchanged; the blueprint tools strip thenulls the strict contract emits so downstream stays clean.Tool-only assistant turns failed to persist.
ai_messages.contentis required, but an assistant turn that only calls a tool has no text, so the insert failed, the turn was dropped, and the next turn lost context (the agent re-proposed instead of applying the confirmed blueprint).ObjectQLConversationService.addMessagenow synthesizes a readable placeholder from the tool names ((called propose_blueprint)) plus a defensive non-empty fallback.With both fixes the full plan-first loop runs end-to-end on OpenAI models: propose → confirm → batch-draft objects/views/dashboards/app → review/diff → publish.
424ab26: fix(seed): reject object-wrapped relationship references and constrain them at compile time
Seed datasets resolve
lookup/master_detailreferences by matching the valueagainst the target record's externalId — so the value must be the plain natural-key
string (e.g.
account: 'Acme Corp'), never a wrapper object likeaccount: { externalId: 'Acme Corp' }. The wrapper was silently skipped by theloader, fell through unresolved, and reached the SQL driver as a non-bindable value —
masked on an always-empty
:memory:DB but crashing on a persistent one with"SQLite3 can only bind numbers, strings, bigints, buffers, and null" once seeds re-ran
as updates.
defineDatasetnow constrains reference fields tostring | nullat compile time(derived from each field's
type), so the object form is a type error.SeedLoaderServicenow fails loudly with an actionable message (and drops the valueinstead of handing it to the driver) when a reference is an object — consistent
behavior across all drivers, no longer silently masked.
@objectstack/express@7.8.0
Patch Changes
@objectstack/fastify@7.8.0
Patch Changes
@objectstack/hono@7.8.0
Patch Changes
@objectstack/nestjs@7.8.0
Patch Changes
@objectstack/nextjs@7.8.0
Patch Changes
@objectstack/nuxt@7.8.0
Patch Changes
@objectstack/sveltekit@7.8.0
Patch Changes
@objectstack/client@7.8.0
Patch Changes
@objectstack/client-react@7.8.0
Patch Changes
@objectstack/connector-mcp@7.8.0
Patch Changes
@objectstack/connector-openapi@7.8.0
Patch Changes
@objectstack/connector-rest@7.8.0
Patch Changes
@objectstack/connector-slack@7.8.0
Patch Changes
@objectstack/core@7.8.0
Patch Changes
@objectstack/formula@7.8.0
Patch Changes
f01f9fa: fix(formula): hydrate ISO date/datetime strings on CEL
no such overloadfault (Date-typed formula fields always evaluate to null — objectql applyFormulaPlan binds raw string values + silently swallows the CEL type fault (ADR-0032 §1c) #1530)Date-typed formula fields and date predicates always evaluated to
null:Field.date/Field.datetimeserialize to ISO strings, and cel-js compared theraw string against the
google.protobuf.Timestampfromtoday()/now()/daysFromNow(), raisingno such overload(swallowed to null). The existingnumeric-string fault-retry (automation: flow conditions on numeric string-serialized fields (rating/currency/percent) fault under strict CEL and silently dead-end the flow (sibling of #1530) #1534) is now extended to also coerce strict ISO-8601
date/date-time strings to
Datebefore retrying once, fixing every caller(formula fields, flow conditions, validation/workflow predicates). Hydration runs
only after a fault, so clean expressions are never re-interpreted and genuine
non-temporal strings still fault loudly.
Updated dependencies [06f2bbb]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/metadata@7.8.0
Patch Changes
@objectstack/metadata-core@7.8.0
Patch Changes
@objectstack/metadata-fs@7.8.0
Patch Changes
@objectstack/observability@7.8.0
Patch Changes
@objectstack/platform-objects@7.8.0
Patch Changes
@objectstack/driver-memory@7.8.0
Patch Changes
@objectstack/driver-mongodb@7.8.0
Patch Changes
@objectstack/driver-sql@7.8.0
Patch Changes
@objectstack/driver-sqlite-wasm@7.8.0
Patch Changes
@objectstack/embedder-openai@7.8.0
Patch Changes
@objectstack/knowledge-memory@7.8.0
Patch Changes
@objectstack/knowledge-ragflow@7.8.0
Patch Changes
@objectstack/plugin-approvals@7.8.0
Patch Changes
@objectstack/plugin-audit@7.8.0
Patch Changes
@objectstack/plugin-auth@7.8.0
Patch Changes
@objectstack/plugin-dev@7.8.0
Patch Changes
@objectstack/plugin-email@7.8.0
Patch Changes
@objectstack/plugin-hono-server@7.8.0
Patch Changes
@objectstack/plugin-mcp-server@7.8.0
Patch Changes
@objectstack/plugin-msw@7.8.0
Patch Changes
@objectstack/plugin-org-scoping@7.8.0
Patch Changes
@objectstack/plugin-reports@7.8.0
Patch Changes
@objectstack/plugin-security@7.8.0
Patch Changes
@objectstack/plugin-sharing@7.8.0
Patch Changes
@objectstack/plugin-trigger-record-change@7.8.0
Patch Changes
@objectstack/plugin-trigger-schedule@7.8.0
Patch Changes
@objectstack/plugin-webhooks@7.8.0
Patch Changes
@objectstack/rest@7.8.0
Patch Changes
a75823a: feat(metadata): expose pending DRAFT metadata (ADR-0033 draft discoverability)
AI-authored metadata lands as drafts (
sys_metadatarows withstate='draft', bound to an app package), but the only list path —getMetaItems— reads the active registry, so drafts were invisible: a just-built app package looked empty and there was no "pending changes" surface.SysMetadataRepository.listDrafts({type?, packageId?})lists draft rows (mirrorslist()but scoped tostate='draft', optionally narrowed by package), returning a light header projection (no body) withpackageId.protocol.listDrafts({packageId?, type?, organizationId?})exposes it over the overlay repo.GET /api/v1/meta/_drafts?packageId=&type=surfaces it to the console. Registered in the REST server before the greedy/meta/:typeroute (and mirrored in the dispatcher) so_draftsis never captured as a metadata type name.Read-only; no behavior change to existing list/publish paths. Powers the upcoming Studio "drafts/pending changes" view and draft-aware package contents.
Updated dependencies [06f2bbb]
Updated dependencies [4fbb86a]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/runtime@7.8.0
Patch Changes
a75823a: feat(metadata): expose pending DRAFT metadata (ADR-0033 draft discoverability)
AI-authored metadata lands as drafts (
sys_metadatarows withstate='draft', bound to an app package), but the only list path —getMetaItems— reads the active registry, so drafts were invisible: a just-built app package looked empty and there was no "pending changes" surface.SysMetadataRepository.listDrafts({type?, packageId?})lists draft rows (mirrorslist()but scoped tostate='draft', optionally narrowed by package), returning a light header projection (no body) withpackageId.protocol.listDrafts({packageId?, type?, organizationId?})exposes it over the overlay repo.GET /api/v1/meta/_drafts?packageId=&type=surfaces it to the console. Registered in the REST server before the greedy/meta/:typeroute (and mirrored in the dispatcher) so_draftsis never captured as a metadata type name.Read-only; no behavior change to existing list/publish paths. Powers the upcoming Studio "drafts/pending changes" view and draft-aware package contents.
4fbb86a: feat(packages): consolidate the package subsystem so AI-built app packages surface in Studio
The package subsystem was split across two stores that never met: the in-memory
SchemaRegistry(what the dispatcher's/api/v1/packageslist/detail andgetMetaItems({type:'package'})read — i.e. Studio's package selector) and the durablesys_packagestable (where the AI's auto app package, and anypackage-service publish,were written). Nothing reconciled the two, so an AI-created
app.<name>package neverappeared in Studio.
This unifies them around one write primitive and one read source:
protocol.installPackageis now implemented (it was declared-but-missing). It is thesingle canonical write path: it registers the package in the in-memory registry and
best-effort persists it to
sys_packagesvia thepackageservice. Non-fatal when nopackageservice is wired (registry write still succeeds).POST /api/v1/packagesroutes throughprotocol.installPackage(fallingback to the bare registry write when the protocol is unavailable), so HTTP installs are
durable too.
@objectstack/service-packagereconcilessys_packagesback into the registry onboot, without clobbering filesystem-registered packages — so persisted packages survive a
restart and stay visible in the registry-backed read paths.
@objectstack/service-aiapply_blueprintnow homes an app viaprotocol.installPackage(falling back to the legacypackage-service publish), so theapp package lands where Studio reads it.
Still the legacy
package_idplane — sealedsys_package_versionversioning andcross-environment promotion remain ADR-0027 follow-ups.
e631f1e: feat(metadata): publish a whole app's drafts in one shot (ADR-0033)
After an AI builds an app, its metadata is drafted (bound to an app package) and
had to be published one item at a time. The package-level
POST /packages/:id/publishneeds the
metadataservice (503 when absent, e.g. the showcase) and reads thein-memory registry, not the drafts.
protocol.publishPackageDrafts({ packageId })promotes everysys_metadatadraft row bound to the package to active by reusing the per-item
publishMetaItemprimitive (overridable/lock guards + runtime registryrefresh). Per-item failures are collected, not fatal. No
metadata-servicedependency.
POST /api/v1/packages/:id/publish-draftsexposes it (distinct from theregistry-based
/publish), returning{ success, publishedCount, failedCount, published, failed }.Verified live: an AI-built
app.asset_management(4 drafts) published in one call —all 4 promoted to active, drafts cleared, draft objects became queryable.
424ab26: fix(seed): reject object-wrapped relationship references and constrain them at compile time
Seed datasets resolve
lookup/master_detailreferences by matching the valueagainst the target record's externalId — so the value must be the plain natural-key
string (e.g.
account: 'Acme Corp'), never a wrapper object likeaccount: { externalId: 'Acme Corp' }. The wrapper was silently skipped by theloader, fell through unresolved, and reached the SQL driver as a non-bindable value —
masked on an always-empty
:memory:DB but crashing on a persistent one with"SQLite3 can only bind numbers, strings, bigints, buffers, and null" once seeds re-ran
as updates.
defineDatasetnow constrains reference fields tostring | nullat compile time(derived from each field's
type), so the object form is a type error.SeedLoaderServicenow fails loudly with an actionable message (and drops the valueinstead of handing it to the driver) when a reference is an object — consistent
behavior across all drivers, no longer silently masked.
Updated dependencies [06f2bbb]
Updated dependencies [a75823a]
Updated dependencies [4fbb86a]
Updated dependencies [e631f1e]
Updated dependencies [f01f9fa]
Updated dependencies [6fc2678]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/service-analytics@7.8.0
Patch Changes
@objectstack/service-automation@7.8.0
Patch Changes
@objectstack/service-cache@7.8.0
Patch Changes
@objectstack/service-cluster@7.8.0
Patch Changes
@objectstack/service-cluster-redis@7.8.0
Patch Changes
@objectstack/service-datasource@7.8.0
Patch Changes
@objectstack/service-feed@7.8.0
Patch Changes
@objectstack/service-i18n@7.8.0
Patch Changes
@objectstack/service-job@7.8.0
Patch Changes
@objectstack/service-knowledge@7.8.0
Patch Changes
@objectstack/service-messaging@7.8.0
Patch Changes
@objectstack/service-package@7.8.0
Patch Changes
4fbb86a: feat(packages): consolidate the package subsystem so AI-built app packages surface in Studio
The package subsystem was split across two stores that never met: the in-memory
SchemaRegistry(what the dispatcher's/api/v1/packageslist/detail andgetMetaItems({type:'package'})read — i.e. Studio's package selector) and the durablesys_packagestable (where the AI's auto app package, and anypackage-service publish,were written). Nothing reconciled the two, so an AI-created
app.<name>package neverappeared in Studio.
This unifies them around one write primitive and one read source:
protocol.installPackageis now implemented (it was declared-but-missing). It is thesingle canonical write path: it registers the package in the in-memory registry and
best-effort persists it to
sys_packagesvia thepackageservice. Non-fatal when nopackageservice is wired (registry write still succeeds).POST /api/v1/packagesroutes throughprotocol.installPackage(fallingback to the bare registry write when the protocol is unavailable), so HTTP installs are
durable too.
@objectstack/service-packagereconcilessys_packagesback into the registry onboot, without clobbering filesystem-registered packages — so persisted packages survive a
restart and stay visible in the registry-backed read paths.
@objectstack/service-aiapply_blueprintnow homes an app viaprotocol.installPackage(falling back to the legacypackage-service publish), so theapp package lands where Studio reads it.
Still the legacy
package_idplane — sealedsys_package_versionversioning andcross-environment promotion remain ADR-0027 follow-ups.
Updated dependencies [06f2bbb]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@objectstack/service-queue@7.8.0
Patch Changes
@objectstack/service-realtime@7.8.0
Patch Changes
@objectstack/service-settings@7.8.0
Patch Changes
@objectstack/service-storage@7.8.0
Patch Changes
@objectstack/types@7.8.0
Patch Changes
@objectstack/account@7.8.0
@objectstack/console@7.8.0
create-objectstack@7.8.0
objectstack-vscode@7.8.0
@objectstack/example-crm@4.0.36
Patch Changes
@objectstack/example-showcase@0.1.6
Patch Changes
6b60068: fix(cli):
objectstack devpersists data by default (no more:memory:wipe on restart)objectstack devhistorically fell back to a:memory:SQLite database when no--database/OS_DATABASE_URLwas given, so every restart silently wiped all data and AI-authored metadata — you'd build an app, restart, and it would be gone, which makes local app-building unusable.devnow defaults to a persistent, project-anchored SQLite file at<cwd>/.objectstack/data/dev.db(gitignored, per-project). Existing opt-outs are unchanged and take precedence:--fresh(ephemeral temp DB),--database <url>,OS_DATABASE_URL/DATABASE_URL, or an explicit in-memory driver (--database-driver memory/OS_DATABASE_DRIVER=memory). Resolution is extracted into the testableresolveDefaultDevDbUrl()helper.The app-showcase example drops its explicit
:memory:datasource override (which would otherwise route data back to memory and defeat the new default), so it persists across restarts out of the box.Updated dependencies [06f2bbb]
Updated dependencies [a75823a]
Updated dependencies [4fbb86a]
Updated dependencies [e631f1e]
Updated dependencies [36719db]
Updated dependencies [424ab26]
@example/app-todo@4.0.36
Patch Changes